#include <my_header.h>

/* Usage: ./1_stdout filename */
int main(int argc, char *argv[]){                                  
    ARGS_CHECK(argc, 2);
    int fd = open(argv[1],O_WRONLY | O_CREAT | O_TRUNC,
                  0666);
    ERROR_CHECK(fd, -1, "open");

    // 备份标准输出的fd
    int temp = dup(STDOUT_FILENO);
    // 首次重定向到文件 缓冲区满缓冲 结束时才会刷新缓冲区
    // 也可以手动刷新
    // 将标准输出重定向指向文件
    dup2(fd, STDOUT_FILENO);
    printf("输出到文件！\n");

    // 因为是满缓冲 只会输出到文件
    // 将标准输出重新重定向到终端
    dup2(temp, STDOUT_FILENO);
    // 
    printf("不会输出到终端\n");

    //再次将标准输出重定向文件
    dup2(fd, STDOUT_FILENO);
    printf("输出到文件\n");

    close(fd);
    return 0;
}

#if 0

按照我们的理解，这段代码将使得标准输出在终端和文件之间
"横跳"：
"how are u\n"将在文件中输出
"I'm fine, and you?\n"将在终端打印
"Me too.\n"又将在文件中输出

但实际上，这三段文本都将输出到文件，这是为什么呢？
这就涉及到操作系统、C标准库对标准输出缓冲区模式的管理
了，第一次使用stdout时的上下文（它指向的是终端还是文
件）将决定stdout的缓冲区刷新机制，并且在整个进程生命周
期，这个刷新机制将默认保持不变：

如果第一次使用stdout时它指向一个终端（比如用printf），
此时缓冲区就是行缓冲的。
如果第一次使用时stdout被重定向到文件或其他非终端设备，缓
冲区就变成了满缓冲区，这意味着缓冲区会积累输出直到满了
或者手动刷新。

比如上面的代码：
虽然重定向都成功了，但由于stdout缓冲区的性质是满缓冲区
，所以只能在最终进程结束时，刷新缓冲区，将所有内容
全部输出到文件中。
#endif
